package com.miracle.toolbox.keyword;



import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.*;

/**
 * 初始化敏感词库，将敏感词加入到HashMap中，构建DFA算法模型
 */
public class KeywordHandler {
    private static final Logger log = LoggerFactory.getLogger(KeywordHandler.class);

    private static KeywordHandler instance = new KeywordHandler();
    private boolean initFlag = false; //是否已经初始化
    private boolean enableKeyword = false;  //是否开启关键字过滤
    public static final String ENCODING = "UTF-8"; //字符编码
    private Set<String> keywordSet;  //敏感词库
    private HashMap<String, String> keywordMap;  // DFA模型

    private KeywordHandler(){
    }

    public static KeywordHandler getInstance(){
        return instance;
    }

    /**
     * 初始化关键信息
     */
    public KeywordHandler initKeyWord(Set<String> keywordSet){
        if (initFlag) throw new RuntimeException("请勿重复初始化");
        initFlag = true;
        reloadSensitiveWord(keywordSet);
        return this;
    }

    /**
     * 读取敏感词库，将敏感词放入HashSet中，构建一个DFA算法模型
     */
    private KeywordHandler addSensitiveWordToHashMap() {
        keywordMap = new HashMap(keywordSet.size());
        String key;
        Map nowMap;
        Map<String, String> newWorMap;

        //迭代keywordSet
        Iterator<String> iterator = keywordSet.iterator();
        while(iterator.hasNext()){
            key = iterator.next(); //关键字
            nowMap = keywordMap;
            for(int i = 0 ; i < key.length() ; i++){
                char keyChar = key.charAt(i); //转换成char型
                Object wordMap = nowMap.get(keyChar);  //获取

                if(wordMap != null){ //如果存在该key，直接赋值
                    nowMap = (Map) wordMap;
                } else{ //不存在则，则构建一个map，同时将isEnd设置为0，因为他不是最后一个
                    newWorMap = new HashMap<>();
                    newWorMap.put("isEnd", "0"); //不是最后一个
                    nowMap.put(keyChar, newWorMap);
                    nowMap = newWorMap;
                }

                if(i == key.length() - 1){
                    nowMap.put("isEnd", "1"); //最后一个
                }
            }
        }
        return this;
    }

    /**
     * 读取敏感词库中的内容，将内容添加到set集合中
     */
    public static Set<String> readSensitiveWordByFile(String path) throws IOException {
        HashSet<String> keywordSet = new HashSet<>();
        File file = new File(path);    //读取文件
        InputStreamReader read = new InputStreamReader(new FileInputStream(file),ENCODING);
        try {
            if(file.isFile() && file.exists()){ //文件流是否存在
                BufferedReader bufferedReader = new BufferedReader(read);
                String txt;
                while((txt = bufferedReader.readLine()) != null){  //读取文件，将文件内容放入到set中
                    keywordSet.add(txt);
                }
            } else{ //不存在抛出异常信息
                throw new RuntimeException("敏感词库文件不存在");
            }
        }finally{
            read.close(); //关闭文件流
        }
        return keywordSet;
    }

    /**
     * 刷新敏感词库
     */
    private KeywordHandler reloadSensitiveWord(Set<String> keywordSet) {
        if (null == keywordSet && keywordSet.size() == 0){ // 词库为空，关闭校验
            log.error("词库为空，自动关闭校验!");
            this.enableKeyword = false;
            return this;
        }
        this.enableKeyword = true;
        this.keywordSet = keywordSet;
        //将敏感词库加入到DFA模型中
        addSensitiveWordToHashMap();

        return this;
    }



    public Set<String> getKeywordSet() { return keywordSet; }

    public HashMap<String, String> getkeywordMap() { return keywordMap; }

    public boolean isEnableKeyword() { return enableKeyword; }

    public void setEnableKeyword(boolean enableKeyword) { this.enableKeyword = enableKeyword; }
}

/**
 * 中 = {
 *      isEnd = 0
 *      国 = {<br>
 *      	 isEnd = 1
 *           人 = {isEnd = 0
 *                民 = {isEnd = 1}
 *                }
 *           男  = {
 *           	   isEnd = 0
 *           		人 = {
 *           			 isEnd = 1
 *           			}
 *           	}
 *           }
 *      }
 *  五 = {
 *      isEnd = 0
 *      星 = {
 *      	isEnd = 0
 *      	红 = {
 *              isEnd = 0
 *              旗 = {
 *                   isEnd = 1
 *                  }
 *              }
 *      	}
 *      }
 */